home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / program / asprog.EXE / CNTWORDS.ASM < prev    next >
Assembly Source File  |  1996-06-26  |  8KB  |  169 lines

  1. ;
  2. ; Program to count the number of words in a file.  Words are
  3. ; delimited by whitespace, which consists of spaces, tabs,
  4. ; carriage returns, and linefeeds.
  5.  
  6.  
  7.         DOSSEG                             ;select standard segment-ordering
  8.         .MODEL  SMALL                      ;code and data each fit in 64K
  9.         .STACK  200h                       ;512-byte stack
  10.         .DATA
  11. Count           DW    0                    ;used to count words
  12. InWhitespace    DB    ?                    ;set to 1 when the last
  13.                                            ; character read was whitespace
  14. TempChar        DB    ?                    ;temporary storage used by
  15.                                            ; GetNextCharacter
  16. Result          DB    'Word count: ', 5 DUP (?)
  17.                                            ;string printed to report the count
  18. CountInsertEnd  LABEL BYTE                 ;used to find the end of the area the
  19.                                            ; count value string is stored in
  20.                 DB    0dh,0ah,'$'
  21.                                            ;DOS fn #9 expects strings to end with
  22.                                            ; a dollar sign
  23.         .CODE
  24. ProgramStart:
  25.         mov     ax,@data
  26.         mov     ds,ax                      ;point DS to the .DATA segment
  27.         mov     [InWhitespace],1           ;assume we're in whitespace, since
  28.                                            ; the first non-whitespace we'll find
  29.                                            ; will mark the start of a word
  30. CountLoop:
  31.         call    GetNextCharacter           ;get next character to check
  32.         jz      CountDone                  ;...if any
  33.         call    IsCharacterWhitespace      ;is it whitespace?
  34.         jz      IsWhitespace               ;yes
  35.         cmp     [InWhitespace],0           ;character is not
  36.                                            ; whitespace-are we currently in
  37.                                            ; whitespace?
  38.         jz      CountLoop                  ;we're not in whitespace, and the
  39.                                            ; character isn't whitespace, so
  40.                                            ; we're done with this character
  41.         inc     [Count]                    ;we are in whitespace, and the
  42.                                            ; character is not whitespace, so
  43.                                            ; we just found the start of a new word
  44.         mov     [InWhitespace],0           ;mark that we're no longer in whitespace
  45.         jmp     CountLoop                  ;do the next character
  46. IsWhitespace:
  47.         mov     [InWhitespace],1           ;mark that we're in whitespace
  48.         jmp     CountLoop                  ;do the next character
  49. ;
  50. ; We're done counting--report the results.
  51. ;
  52. CountDone:
  53.         mov     ax,[Count]                 ;number to convert to a string
  54.         mov     bx,OFFSET CountInsertEnd-1 ;point to the end of the string to
  55.                                            ; put the number in
  56.         mov     cx,5                       ;number of digits to convert
  57.         call    ConvertNumberToString      ;make the number a string
  58.         mov     bx,OFFSET Result           ;point to result string
  59.         call    PrintString                ;print the count
  60.         mov     ah,4ch                     ;DOS terminate program fn #
  61.         int     21h                        ;end the program
  62. ;
  63. ; Subroutine to get the next character from the standard input.
  64. ;
  65. ; Input: None
  66. ;
  67. ; Output:
  68. ;       AL = character, if one was available
  69. ;       Z flag = 0 (NZ) if character available,
  70. ;              = 1 (Z) if end of file reached
  71. ;
  72. ; Registers destroyed: AH, BX, CX, DX
  73. ;
  74. GetNextCharacter        PROC
  75.         mov     ah,3fh                     ;DOS read from file fn #
  76.         mov     bx,0                       ;standard input handle
  77.         mov     cx,1                       ;read one character
  78.         mov     dx,OFFSET TempChar         ;put the character in TempChar
  79.         int     21h                        ;get the next character
  80.         jc      NoCharacterRead            ;if DOS reports an error, then treat
  81.                                            ; it as the end of the file
  82.         cmp     [TempChar],1ah             ;was it Control-Z?
  83.                                            ; (marks end of some files)
  84.         jne     NotControlZ                ;no
  85. NoCharacterRead:
  86.         sub     ax,ax                      ;mark no character read
  87. NotControlZ:
  88.         and     ax,ax                      ;set Z flag to reflect whether a
  89.                                            ; character was read (NZ), or the
  90.                                            ; end of the file was reached (Z).
  91.                                            ; Note that DOS fn #3fh sets AX to
  92.                                            ; the number of characters read
  93.         mov     al,[TempChar]              ;return the character read
  94.         ret                                ;done
  95. GetNextCharacter        ENDP
  96. ;
  97. ; Subroutine to report whether a given character is whitespace.
  98. ;
  99. ; Input:
  100. ;       AL = character to check
  101. ;
  102. ; Output:
  103. ;       Z flag = 0 (NZ) if character is not whitespace
  104. ;              = 1 (Z) if character is whitespace
  105. ;
  106. ; Registers destroyed: none
  107. ;
  108. IsCharacterWhitespace   PROC
  109.         cmp     al,' '                     ;is it a space?
  110.         jz      EndIsCharacterWhitespace   ;if so, it's whitespace
  111.         cmp     al,09h                     ;is it a tab?
  112.         jz      EndIsCharacterWhitespace   ;if so, it's whitespace
  113.         cmp     al,0dh                     ;is it a carriage return?
  114.         jz      EndIsCharacterWhitespace   ;if so, it's whitespace
  115.         cmp     al,0ah                     ;is it a linefeed? If so,
  116.                                            ; it's whitespace, so return Z;
  117.                                            ; if not, it's not whitespace,
  118.                                            ; so return NZ as set by cmp
  119. EndIsCharacterWhitespace:
  120.         ret
  121. IsCharacterWhitespace   ENDP
  122. ;
  123. ; Subroutine to convert a binary number to a text string.
  124. ;
  125. ; Input:
  126. ;       AX = number to convert
  127. ;       DS:BX = pointer to end of string to store text in
  128. ;       CX = number of digits to convert
  129. ;
  130. ; Output: None
  131. ;
  132. ; Registers destroyed: AX, BX, CX, DX, SI
  133. ;
  134. ConvertNumberToString   PROC
  135.         mov     si,10                      ;used to divide by 10
  136. ConvertLoop:
  137.         sub     dx,dx                      ;convert AX to doubleword in DX:AX
  138.         div     si                         ;divide number by 10. Remainder is in
  139.                                            ; DX--this is a one-digit decimal
  140.                                            ; number. Number/10 is in AX
  141.         add     dl,'0'                     ;convert remainder to a text character
  142.         mov     [bx],dl                    ;put this digit in the string
  143.         dec     bx                         ;point to the location for the
  144.                                            ; next most-significant digit
  145.         loop    ConvertLoop                ;do the next digit, if any
  146.         ret
  147. ConvertNumberToString   ENDP
  148. ;
  149. ; Subroutine to print a string on the display.
  150. ;
  151. ; Input:
  152. ;       DS:BX = pointer to string to print
  153. ;
  154. ; Output: None
  155. ;
  156. ; Registers destroyed: None
  157. ;
  158. PrintString     PROC
  159.         push    ax
  160.         push    dx                         ;preserve registers in this subroutine
  161.         mov     ah,9                       ;DOS print string function #
  162.         mov     dx,bx                      ;point DS:DX to the string to print
  163.         int     21h                        ;invoke DOS to print the string
  164.         pop     dx                         ;restore registers we changed
  165.         pop     ax
  166.         ret
  167. PrintString     ENDP
  168.         END     ProgramStart
  169.